package org.example;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.util.DateUtils;
import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.xslf.usermodel.*;
import org.example.excel.WordDTO;

import java.awt.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author 10071
 */
public class WordPPT {

    static String inputFilePath = "D:/zhongruan/学习笔记/英语视频/单词ppt/template.pptx";
    static String outputFilePath = "D:/zhongruan/学习笔记/英语视频/单词ppt/2025";
    static String excelPath = "D:/zhongruan/学习笔记/英语视频/单词ppt/word.xlsx";
    /** 文本框左边距 */
    static int MARGIN_LEFT = 30;

    public static void main(String[] args) {
        List<WordDTO> wordDTOS = readExcel(excelPath);
        try (XMLSlideShow ppt = new XMLSlideShow(new FileInputStream(inputFilePath))) {
            for (WordDTO wordDTO : wordDTOS) {
                System.out.println(wordDTO.toString());
                System.out.println();
                fillPPT(ppt, wordDTO);
            }
            String pptPath = outputFilePath + "/" + DateUtils.format(new Date(), "yyyyMMdd") + ".pptx";
            // 保存最终的 PPT 文件
            try (FileOutputStream out = new FileOutputStream(pptPath)) {
                ppt.write(out);
            }
            System.out.println();
            System.out.println("PPTX文件已成功修改并保存！");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据WordDTO对象填充PPT。
     * @param ppt     PPT对象
     * @param wordDTO 包含填充PPT所需信息的WordDTO对象
     */
    public static void fillPPT(XMLSlideShow ppt, WordDTO wordDTO) {
        List<XSLFSlide> slides = ppt.getSlides();
        // 获取幻灯片的默认字体设置
        // 使用第一页作为模板
        XSLFSlide slideTemplate = ppt.getSlides().get(0);
        // 创建新的幻灯片
        XSLFSlide newSlide = ppt.createSlide(slideTemplate.getSlideLayout());
        // 删除示例文本框
        for (Shape shape : newSlide.getShapes()) {
            if (shape instanceof XSLFAutoShape) {
                // 删除该文本框
                newSlide.removeShape((XSLFShape) shape);
            }
        }
        // 使用WordDTO填充PPT
        fillWordAndSound(newSlide, wordDTO.getWord() + " " + wordDTO.getSoundmark());
        fillExplain(newSlide, wordDTO.getExplain());
        fillRememberTitle(newSlide);
        fillRemember(newSlide, wordDTO.getRemember());
        fillExample(newSlide, wordDTO.getExample());
        // 删除示例文本框
        if ("内容占位符 2".equals(newSlide.getShapes().get(0).getShapeName())) {
            newSlide.removeShape(newSlide.getShapes().get(0));
        }
    }

    /**
     * 在新的幻灯片中填充单词和音标。
     * @param newSlide 要填充的幻灯片
     * @param content  要填充的内容
     */
    public static void fillWordAndSound(XSLFSlide newSlide, String content) {
        // 创建文本框
        XSLFAutoShape textBox = newSlide.createAutoShape();
        textBox.setShapeType(ShapeType.RECT);
        // 设置文本框位置和大小
        textBox.setAnchor(new Rectangle(MARGIN_LEFT, 10, 600, 50));
        // 设置文本内容
        textBox.setText(content);
        XSLFTextRun wordAndSound = textBox.getTextParagraphs().get(0).getTextRuns().get(0);
        wordAndSound.setFontFamily("微软雅黑");
        wordAndSound.setFontSize(44.0);
        wordAndSound.setBold(true);
    }

    /**
     * 在新的幻灯片中填充解释内容。
     * @param newSlide 要填充的幻灯片
     * @param content  要填充的解释内容
     */
    public static void fillExplain(XSLFSlide newSlide, String content) {
        // 创建文本框
        XSLFAutoShape textBox = newSlide.createAutoShape();
        textBox.setShapeType(ShapeType.RECT);
        // 设置文本框位置和大小
        textBox.setAnchor(new Rectangle(MARGIN_LEFT, 100, 600, 100));
        // 设置文本内容
        textBox.setText(content);
        textBox.getTextParagraphs().forEach(textParagraph -> {
            XSLFTextRun explain = textParagraph.getTextRuns().get(0);
            explain.setFontFamily("微软雅黑");
            explain.setFontSize(24.0);
        });
    }

    /**
     * 生成巧记标题
     * @param newSlide
     */
    public static void fillRememberTitle(XSLFSlide newSlide) {
        // 创建文本框
        XSLFAutoShape textBox = newSlide.createAutoShape();
        textBox.setShapeType(ShapeType.RECT);
        // 设置文本框位置和大小
        textBox.setAnchor(new Rectangle(MARGIN_LEFT, 200, 600, 30));
        // 设置文本内容
        XSLFTextParagraph paragraph = textBox.addNewTextParagraph();
        XSLFTextRun textRun = paragraph.addNewTextRun();
        textRun.setText("巧记：");
        textRun.setFontFamily("微软雅黑");
        textRun.setFontSize(24.0);
        textRun.setFontColor(Color.RED);
    }

    /**
     * 在新的幻灯片中填充记忆内容。
     * @param newSlide 要填充的幻灯片
     * @param content  要填充的记忆内容
     */
    public static void fillRemember(XSLFSlide newSlide, String content) {
        // 创建文本框
        XSLFAutoShape textBox = newSlide.createAutoShape();
        textBox.setShapeType(ShapeType.RECT);
        // 设置文本框位置和大小
        textBox.setAnchor(new Rectangle(MARGIN_LEFT, 230, 800, 100));
        List<String> lines = getLines(content);
        for (int i = 0; i < lines.size(); i++) {
            String text = lines.get(i);
            XSLFTextParagraph paragraph = textBox.addNewTextParagraph();
            if (i % 2 == 0) {
                // 奇数行是拆词
                String[] words = text.split("/s+");
                for (String word : words) {
                    for (int j = 0; j < word.length(); j++) {
                        char c = word.charAt(j);
                        XSLFTextRun textRun = paragraph.addNewTextRun();
                        textRun.setText(String.valueOf(c));
                        textRun.setFontFamily("微软雅黑");
                        textRun.setFontSize(24.0);
                        // 英文设置颜色为橙色
                        if (String.valueOf(c).matches("[a-zA-Z]+")) {
                            textRun.setFontColor(Color.ORANGE);
                        }
                    }
                    XSLFTextRun blank = paragraph.addNewTextRun();
                    blank.setText(" ");
                }
            } else {
                // 偶数行是造句
                List<String> strings = StoryUtil.splitText(text);
                for (String s : strings) {
                    if (s.startsWith("【")) {
                        fillString(paragraph, "【");
                        fillString(paragraph, s.replace("【", "").replace("】", ""), Color.YELLOW);
                        fillString(paragraph, "】");
                    } else if (s.startsWith("(")) {
                        fillString(paragraph, "(");
                        fillString(paragraph, s.replace("(", "").replace(")", ""), Color.ORANGE);
                        fillString(paragraph, ")");
                    } else if (s.startsWith("（")) {
                        fillString(paragraph, "（");
                        fillString(paragraph, s.replace("（", "").replace("）", ""), Color.ORANGE);
                        fillString(paragraph, "）");
                    } else {
                        fillString(paragraph, s);
                    }
                }
            }
            paragraph.addLineBreak();
        }
    }

    /**
     * 在新的幻灯片中填充例句。
     * @param newSlide 要填充的幻灯片
     * @param content  要填充的例句内容
     */
    public static void fillExample(XSLFSlide newSlide, String content) {
        // 创建文本框
        XSLFAutoShape textBox = newSlide.createAutoShape();
        textBox.setShapeType(ShapeType.RECT);
        // 设置文本框位置和大小
        textBox.setAnchor(new Rectangle(MARGIN_LEFT, 340, 600, 100));
        // 设置文本内容
        textBox.setText(content);
        textBox.getTextParagraphs().forEach(textParagraph -> {
            XSLFTextRun explain = textParagraph.getTextRuns().get(0);
            explain.setFontFamily("微软雅黑");
            explain.setFontSize(20.0);
        });
    }

    /**
     * 在指定的段落中填充字符串，不设置文本颜色。
     * @param paragraph 要填充的段落
     * @param text      要填充的字符串
     */
    public static void fillString(XSLFTextParagraph paragraph, String text) {
        fillString(paragraph, text, null);
    }

    /**
     * 在指定的段落中填充字符串，并设置文本颜色。
     * @param paragraph 要填充的段落
     * @param text      要填充的字符串
     * @param color     文本颜色，如果为null，则不设置文本颜色
     */
    public static void fillString(XSLFTextParagraph paragraph, String text, Color color) {
        XSLFTextRun textRun = paragraph.addNewTextRun();
        textRun.setFontFamily("微软雅黑");
        textRun.setFontSize(24.0);
        textRun.setText(text);
        if (color != null) {
            textRun.setFontColor(color);
        }
    }

    /**
     * 将给定的字符串内容按行分割并返回一个字符串列表。
     * @param content 待分割的字符串内容
     * @return 包含分割后行的字符串列表
     */
    public static List<String> getLines(String content) {
        List<String> lines = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new StringReader(content))) {
            String line;
            while ((line = reader.readLine()) != null) {
                lines.add(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return lines;
    }

    /**
     * 从指定路径的Excel文件中读取数据，并返回包含WordDTO对象的列表。
     * @param filePath Excel文件的路径
     * @return 包含WordDTO对象的列表
     */
    public static List<WordDTO> readExcel(String filePath) {
        List<WordDTO> list = new ArrayList<>();
        EasyExcel.read(filePath, WordDTO.class, new AnalysisEventListener<WordDTO>() {

            @Override
            public void invoke(WordDTO wordDTO, AnalysisContext analysisContext) {
                list.add(wordDTO);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {

            }
        }).sheet().doRead();
        return list;
    }
}
